/// author stevenHu
///
/// created by hujintao
/// created at 2022/4/11
import 'dart:async';
import 'dart:io';
import 'dart:math' as dart_math;
import 'dart:math';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:hk_base/hk_log.dart';
import 'components/dialog/general_dialog.dart';
import 'image_enum.dart';

/// 代码块拦截
void hkTryCatch(Function? f) {
  try {
    f?.call();
  } catch (e, stack) {
    HkLog.e('$e');
    HkLog.e('$stack');
  }
}

/// 延迟调用
/*
hkSetTimeout(() {
  //xxx
}, Duration(milliseconds: 500));
 */
void hkSetTimeout(back, Duration duration) {
  Timer(duration, back);
}

class HkUtils {

  /// 获取本地Mock数据【加载本地json数据】
  /*
  var responseJson = await HkUtils.mock(url: 'get_box_list');
  HkLog.d("data>>>>$responseJson");
  */
  static Future<dynamic> mock({
    String url = "",
    bool needFullPath = false,
    String fullPath = "",
  }) async {
    var path = "";
    if (!needFullPath) {
      path = 'mock/$url.json';
    } else {
      path = fullPath;
    }
    var responseStr = await rootBundle.loadString(path);
    var responseJson = json.decode(responseStr);
    return responseJson['data'];
  }

  /// 设置状态栏和导航栏
  static setSystemUi() {
    if (Platform.isAndroid) {
      SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle(
          statusBarColor: Colors.transparent,
          statusBarBrightness: Brightness.light,
          statusBarIconBrightness: Brightness.dark,
          systemNavigationBarDividerColor: Colors.transparent,
          systemNavigationBarColor: Colors.white,
          systemNavigationBarIconBrightness: Brightness.dark);
      SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
    }
  }

  /// 是否 release
  static bool get isRelease => const bool.fromEnvironment("dart.vm.product");

  /// 加载本地Asset图片
  static ImageProvider getAssetImage(String? name, {String format = 'png'}) {
    return AssetImage('assets/images/$name.$format');
  }

  /// 获取本地图片地址
  static String getImgPath(String? name,
      {HKImageFormat format = HKImageFormat.png}) {
    return 'assets/images/$name.${format.value}';
  }

  /// 把角度转为Alignment组件可用参数, 一般用于渐变
  static Map<String, double> parseAngleToAlignment(double deg) {
    deg = 180 - deg;
    double rad = dart_math.pi / 180 * deg;
    double endured = dart_math.pi / 180 * (180 + deg);
    Map<String, double> result = {};

    result['beginX'] = dart_math.cos(rad) * dart_math.sqrt(2);
    result['beginY'] = -dart_math.sin(rad) * dart_math.sqrt(2);
    result['endX'] = dart_math.cos(endured) * dart_math.sqrt(2);
    result['endY'] = -dart_math.sin(endured) * dart_math.sqrt(2);

    return result;
  }

  /// 分割字符 '${cutText(secMod.topleftdata, 8) ?? 0}U'
  static String cutText(dynamic text, int num) {
    var txt = '';
    if (text is String) {
      txt = text.substring(0, text.length < num ? text.length : num);
    } else {
      txt = text.toString().substring(
          0, text.toString().length < num ? text.toString().length : num);
    }
    return txt;
  }

  /// 跳转到小程序
  /*
  # 微信sdk
  fluwx: ^0.6.2
  Utils.goFpdxMiniApp(path: '/pages/my-baseinfo/my-baseinfo');
  */
  static void goFpdxMiniApp({String path = "", withPrefix = true}) async {
    /// 未安装微信
    // bool _isWechatInstalled = await fluwx.isWeChatInstalled();
    // if (!_isWechatInstalled) {
    //   return;
    // }
    //
    // String finalPath = withPrefix && path != null
    //     ? 'pages/starter/starter?launch_type=free&url=${Uri.encodeComponent(path)}'
    //     : path;
    // /// 微信关联公众号media_id
    // const String MEDIA_ID = 'gh_01c089b58dda';
    // fluwx.launchMiniProgram(
    //     username: MEDIA_ID, path: finalPath ?? 'pages/starter/starter');
  }


  ///阴影和圆角装饰器封装
  static BoxDecoration getShadowDecoration({
    ///颜色
    Color? color,

    ///圆角
    double borderRadius = 0,

    ///阴影模糊程度
    double shadowBlurRadius = 0.0,

    /// 阴影向外扩散半径
    double spreadRadius = 0.0,

    ///阴影偏移量
    Offset shadowOffset = Offset.zero,

    ///阴影颜色
    Color shadowColor = Colors.black,

    ///是否需要阴影
    bool needShadow = false,

    /// 是否使用默认的Shadow,通用配置
    bool userDefaultShadow = true,

    /// 阴影参数
    int? elevation = 1,

    /// 渐变色
    Gradient? gradient,
  }) {
    if (needShadow) {
      return BoxDecoration(
        color: color,
        borderRadius: BorderRadius.circular(borderRadius),
        gradient: gradient,
        boxShadow: userDefaultShadow
            ? kElevationToShadow[elevation]
            : [
          BoxShadow(
            color: shadowColor,
            blurRadius: shadowBlurRadius,
            spreadRadius: spreadRadius,
            offset: shadowOffset,
          ),
        ],
      );
    }
    return BoxDecoration(
      color: color,
      gradient: gradient,
      borderRadius: BorderRadius.circular(borderRadius),
    );
  }

  /// [colors] 渐变颜色
  /// [deg] 渐变角度
  static LinearGradient getLinearGradientParams(
      {required List<Color> colors,
        HKGradientType gradientType = HKGradientType.fromLeftToRight,
        double deg = 180,
        List<double>? stops}) {
    if (gradientType == HKGradientType.none) {
      Map<String, double> alignment = parseAngleToAlignment(deg);
      return LinearGradient(
          colors: colors,
          stops: stops,
          begin: Alignment(alignment['beginX']!, alignment['beginY']!),
          end: Alignment(alignment['endX']!, alignment['endY']!));
    } else {
      AlignmentGeometry begin = Alignment.centerLeft;
      AlignmentGeometry end = Alignment.centerRight;
      switch (gradientType) {
        case HKGradientType.fromLeftToRight:
          begin = Alignment.centerLeft;
          end = Alignment.centerRight;
          break;
        case HKGradientType.fromRightToLeft:
          begin = Alignment.centerRight;
          end = Alignment.centerLeft;
          break;
        case HKGradientType.fromTopToBottom:
          begin = Alignment.topCenter;
          end = Alignment.bottomCenter;
          break;
        case HKGradientType.fromBottomToTop:
          begin = Alignment.bottomCenter;
          end = Alignment.topCenter;
          break;
        case HKGradientType.fromBottomLeftToTopRight:
          begin = Alignment.bottomLeft;
          end = Alignment.topRight;
          break;
        case HKGradientType.fromTopRightToBottomLeft:
          begin = Alignment.topRight;
          end = Alignment.bottomLeft;
          break;

        default:
          break;
      }
      return LinearGradient(
          colors: colors, stops: stops, begin: begin, end: end);
    }
  }

  /// 随机色设置
  static getRandomColor() {
    return Color.fromARGB(255, Random.secure().nextInt(255),
        Random.secure().nextInt(255), Random.secure().nextInt(255));
  }

  /// createMaterialColor
  static MaterialColor createMaterialColor(Color color) {
    List strengths = <double>[.05];
    Map swatch = <int?, Color>{};
    final int r = color.red, g = color.green, b = color.blue;

    for (int i = 1; i < 10; i++) {
      strengths.add(0.1 * i);
    }
    for (var strength in strengths) {
      final double ds = 0.5 - strength;
      swatch[(strength * 1000).round()] = Color.fromRGBO(
        r + ((ds < 0 ? r : (255 - r)) * ds).round(),
        g + ((ds < 0 ? g : (255 - g)) * ds).round(),
        b + ((ds < 0 ? b : (255 - b)) * ds).round(),
        1,
      );
    }
    return MaterialColor(color.value, swatch as Map<int, Color>);
  }

  ///防止重复点击【节流与防抖】
  static const deFaultDurationTime = 300;
  static Timer? timer;

  /// 防抖函数
  /// 函数防抖，这里的抖动就是执行的意思，而一般的抖动都是持续的，多次的。
  /// 假设函数持续多次执行，我们希望让它冷静下来再执行。
  /// 也就是当持续触发事件的时候，函数是完全不执行的，等最后一次触发结束的一段时间之后，再去执行。
  static debounce(Function? doSomething, {durationTime = deFaultDurationTime}) {
    timer?.cancel();
    timer = Timer(Duration(milliseconds: durationTime), () {
      doSomething?.call();
      timer = null;
    });
  }

  /// throttle节流
  /// 让函数有节制地执行，而不是毫无节制的触发一次就执行一次。
  /// 什么叫有节制呢？就是在一段时间内，只执行一次。
  /// [func]: 要执行的方法
  // ignore: prefer_typing_uninitialized_variables
  static var lastPopTime;
  static void throttle({required Future Function() func, int seconds = 3}) {
    // 防重复提交
    if (lastPopTime == null ||
        DateTime.now().difference(lastPopTime) > Duration(seconds: seconds)) {
      HkLog.d(lastPopTime);
      lastPopTime = DateTime.now();
      func();
      HkLog.d("允许点击");
    } else {
      HkLog.d("请勿重复点击！");
    }
  }
  /// 毫秒
  static void throttleWithMilliseconds({required Future Function() func, int milliseconds = 1000}) {
    // 防重复提交
    if (lastPopTime == null ||
        DateTime.now().difference(lastPopTime) > Duration(milliseconds: milliseconds)) {
      HkLog.d(lastPopTime);
      lastPopTime = DateTime.now();
      func();
      HkLog.d("允许点击");
    } else {
      HkLog.d("请勿重复点击！");
    }
  }

  //备选方节流方案
  static const String deFaultThrottleId = 'DeFaultThrottleId';
  static Map<String, int> startTimeMap = {deFaultThrottleId: 0};
  static optionalThrottle(Function? doSomething,
      {String throttleId = 'DeFaultThrottleId',
      durationTime = deFaultDurationTime,
      required Function? continueClick}) {
    int currentTime = DateTime.now().millisecondsSinceEpoch;
    if (currentTime - (startTimeMap[throttleId] ?? 0) > durationTime) {
      doSomething?.call();
      startTimeMap[throttleId] = DateTime.now().millisecondsSinceEpoch;
    } else {
      continueClick?.call();
    }
  }
}

class UiUtils {
  /*
  UiUtils.showCommonDialog(
                      context,
                      title: '请确认继续',
                      message: 'IOS支付的用户，匹配失败后无法退款。但可以最高匹配成功率免费报名下一期。',
                      cancelTitle: '取消',
                      confirmTitle: '继续报名',
                      confirmCallback: () {
                      },
                    );
  */

  /// 显示通用对话框
  static showCommonDialog(
      BuildContext context, {
        bool outsideDismiss = true,
        Widget? widgetForMessage,
        String? title = "系统提示",
        String? message = "您确定要退出登录吗？",
        String? cancelTitle = "取消",
        String? confirmTitle = "确定",
        String? prefixText,
        String? markText,
        String? suffixText,
        Function? cancelCallback,
        Function? confirmCallback,
        Function? markCallback,
      }) {
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return GeneralDialog(
            widgetForMessage: widgetForMessage,
            title: title,
            prefixText: prefixText,
            markText: markText,
            suffixText: suffixText,
            message: message,
            cancelTitle: cancelTitle,
            confirmTitle: confirmTitle,
            cancelCallback: cancelCallback,
            confirmCallBack: confirmCallback,
            markCallback: markCallback,
            outsideDismiss: outsideDismiss,
          );
        });
  }
}

class UrlUtils {
  /// 从url解析query
  static Map<String, dynamic> getQueryFromUrl(String url) {
    Map<String, dynamic> query = {};

    // 不带query, 不再解析, 直接返回
    if (url.isEmpty || !url.contains('?')) {
      return query;
    }

    String queryString = url.split('?')[1];

    if (queryString.isEmpty) {
      return query;
    }

    List<String> queryStringItems = queryString.split('&');

    for (var item in queryStringItems) {
      List<String> queryItemKv = item.split('=');
      query[queryItemKv[0]] = queryItemKv[1];
    }

    return query;
  }

  /// 向已有的url拼上query eg: WebviewStorage.url = UrlUtils.addQueryToUrl(link, 'in_fpdx_app=1');
  static String addQueryToUrl(String url, String query) {
    if (url.isEmpty) {
      return url;
    }

    List<String> urlHashSplits = url.split('#');
    String urlWithoutHash = urlHashSplits[0];
    String? hash = urlHashSplits.length == 2 ? urlHashSplits.last : null;

    if (!urlWithoutHash.contains('?')) {
      urlWithoutHash += '?$query';
    } else {
      urlWithoutHash += '&$query';
    }

    if (hash != null) {
      urlWithoutHash += '#$hash';
    }

    return urlWithoutHash;
  }
}
